package musictrackrecommendation;

import java.util.ArrayList;
import java.util.List;

import lastfm.LastfmTrackTrackSubmatrix;

import randomwalk.PreferencesVector;
import randomwalk.QuizSetVerification;
import randomwalk.Submatrix;
import evaluation.HalfLifeUtility;

public class Utils {
	
	/**
	 * Get vector * number
	 * @param vector - multiplying vector
	 * @param number - multiplying number
	 */
	public static void multiply(double[] vector, double number) {
		for (int i = 0; i < vector.length; i++)
			 vector[i] *= number;
	}
	
	/**
	 * @param vector1 - first summand
	 * @param vector2 - second summand
	 * @return vector1 + vector2
	 */
	public static double [] sum(double[] vector1, double[] vector2) {
		double[] sum = new double [vector1.length];
		if (vector1.length == vector2.length) {
			for (int i = 0; i < vector1.length; i++) {
				sum[i] = vector1[i] + vector2[i];
			}
		}
		return sum;
	}
	
    /**
     * @param vector
     * @return taxicab norm of vector
     */
	public static double vectorNorm(double [] vector) {
		double norm = 0.0;
		for (double elem : vector)
			norm += elem;
		return norm;
	}
	
	/**
	 * Bring taxicab norm of vector to 1
	 * @param vector
	 */
	public static void normalizeVector(double [] vector, double requiredNorm) {
		double norm = vectorNorm(vector);
		multiply(vector, requiredNorm/norm);
	}
	
	/**
	 * Bring taxicab norm of coupled (vector1,vector2) to 1
	 * @param vector1 - coupled vector head
	 * @param vector2 - coupled vector tail
	 */
	public static void normalizeVector(double [] vector1, 
			double [] vector2) {
		
		double norm1 = vectorNorm(vector1);
		double norm2 = vectorNorm(vector2);
		double totalNorm = norm1 + norm2;
		
		multiply(vector1, 1.0/totalNorm);
		multiply(vector2, 1.0/totalNorm);
	}	
	
	/**
	 * Bring taxicab norm of coupled (vector1,vector2,vector3) to 1
	 * @param vector1 - coupled vector head
	 * @param vector2 - coupled vector midst
	 * @param vector3 - coupled vector tail
	 */
	public static void normalizeVector(double [] vector1, 
			double [] vector2, double [] vector3) {
		
		double norm1 = vectorNorm(vector1);
		double norm2 = vectorNorm(vector2);
		double norm3 = vectorNorm(vector3);
		double totalNorm = norm1 + norm2 + norm3;
		
		multiply(vector1, 1.0/totalNorm);
		multiply(vector2, 1.0/totalNorm);
		multiply(vector3, 1.0/totalNorm);
	}
	
    /**
     * @param vector
     * @return count of nonzero elements in vector
     */
	public static int nonzeroItemsCount(double [] vector) {
		int count = 0;
		for (double elem : vector){
			if(elem != 0.0)
				count++;
		}
		return count;
	}
	
    /**
     * @param vector1
     * @param vector2
     * @return quadratic divergence between vector1 and vector2 
     * or -1.0 if vectors is not comparable
     * 
     */
	public static double quadraticDivergence(double [] vector1, double [] vector2) {
		double divergence = 0.0;
		if (vector1.length == vector2.length) {
			for (int i = 0; i < vector1.length; i++) {
				divergence += java.lang.Math.pow((vector1[i] - vector2[i]),2.0);
			}
		}
		else {
			divergence = -1.0;
		}
		return divergence;
	}
	
	public static int countCollisions(List<Integer> list) {
		System.out.println(list.toString());
		int collisions = 0;
		for(int i : list) {
			if(list.indexOf(i) != list.lastIndexOf(i))
				collisions++;
		}
		return collisions/2;
	}
	
	// Print result of current RWR step
	public static void printStepResults(PreferencesVector preferencesVector,
			QuizSetVerification verification, int userId, int step) {
		double [] trackPreferences = preferencesVector.getTracks().clone();
		System.out.println("Step " + step);
		ArrayList<Integer> topTracks = verification.prepareTopTracks(trackPreferences, trackPreferences.length);

		System.out.println("Collisions " +	Utils.countCollisions(
				topTracks.subList(0, Math.min(50,topTracks.size()))));
		HalfLifeUtility ev = new HalfLifeUtility(10);
		
		ev.addRecommendation(userId, topTracks, verification);
	}
	
	
	@SuppressWarnings("unused")
	private static Submatrix getDoubleSubmatrix(Submatrix sm) {
		int halfUserUserSize = sm.getRowIds().length;
		int [] rowIds = new int [halfUserUserSize * 2];
		int [] columnIds = new int [halfUserUserSize * 2];
		double [] values = new double [halfUserUserSize * 2];
		
		//arraymerge
		System.arraycopy(sm.getRowIds(), 0, rowIds, 0, halfUserUserSize);
		System.arraycopy(sm.getColumnIds(), 0, rowIds, halfUserUserSize, halfUserUserSize);
		
		System.arraycopy(sm.getColumnIds(), 0, columnIds, 0, halfUserUserSize);
		System.arraycopy(sm.getRowIds(), 0, columnIds, halfUserUserSize, halfUserUserSize);

		System.arraycopy(sm.getValues(), 0, values, 0, halfUserUserSize);
		System.arraycopy(sm.getValues(), 0, values, halfUserUserSize, halfUserUserSize);
		
		return new LastfmTrackTrackSubmatrix(rowIds, columnIds, values, values);
	}
	
	public static String getCommaSeparatedString(ArrayList<Integer> lst) {
		String res = "(";
		for (int elem : lst)
			res +=elem + ",";
		res = res.substring(0, res.length()-1);
		res += ")";
		return res;
	}
	
	public static int[] getIntArray(ArrayList<Integer> lst) {
		int[] res = new int [lst.size()];
		for (int i = 0; i < lst.size(); i++)
			res[i] = lst.get(i);
		return res;
	}
	
	public static double[] getDoubleArray(ArrayList<Double> lst) {
		double[] res = new double[lst.size()];
		for (int i = 0; i < lst.size(); i++)
			res[i] = lst.get(i);
		return res;
	}
}
